home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / STORE1.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  12KB  |  451 lines

  1. /* source/store1.c: store code, updating store inventory, pricing objects
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #include "config.h"
  10. #include "constant.h"
  11. #include "types.h"
  12. #include "externs.h"
  13.  
  14. #ifdef USG
  15. #ifndef ATARIST_MWC
  16. #include <string.h>
  17. #endif
  18. #else
  19. #include <strings.h>
  20. #endif
  21.  
  22. #if defined(LINT_ARGS)
  23. static void insert_store(int, int, int32, struct inven_type *);
  24. static void store_create(int);
  25. #else
  26. static void insert_store();
  27. static void store_create();
  28. #endif
  29.  
  30.  
  31. /* Returns the value for any given object        -RAK-    */
  32. int32 item_value(i_ptr)
  33. register inven_type *i_ptr;
  34. {
  35.   register int32 value;
  36.  
  37.   value = i_ptr->cost;
  38.   /* don't purchase known cursed items */
  39.   if (i_ptr->ident & ID_DAMD)
  40.     value = 0;
  41.   else if (((i_ptr->tval >= TV_BOW) && (i_ptr->tval <= TV_SWORD)) ||
  42.        ((i_ptr->tval >= TV_BOOTS) && (i_ptr->tval <= TV_SOFT_ARMOR)))
  43.     {    /* Weapons and armor    */
  44.       if (!known2_p(i_ptr))
  45.     value = object_list[i_ptr->index].cost;
  46.       else if ((i_ptr->tval >= TV_BOW) && (i_ptr->tval <= TV_SWORD))
  47.     {
  48.       if (i_ptr->tohit < 0)
  49.         value = 0;
  50.       else if (i_ptr->todam < 0)
  51.         value = 0;
  52.       else if (i_ptr->toac < 0)
  53.         value = 0;
  54.       else
  55.         value = i_ptr->cost+(i_ptr->tohit+i_ptr->todam+i_ptr->toac)*100;
  56.     }
  57.       else
  58.     {
  59.       if (i_ptr->toac < 0)
  60.         value = 0;
  61.       else
  62.         value = i_ptr->cost+i_ptr->toac*100;
  63.     }
  64.     }
  65.   else if ((i_ptr->tval >= TV_SLING_AMMO) && (i_ptr->tval <= TV_SPIKE))
  66.     {    /* Ammo            */
  67.       if (!known2_p(i_ptr))
  68.     value = object_list[i_ptr->index].cost;
  69.       else
  70.     {
  71.       if (i_ptr->tohit < 0)
  72.         value = 0;
  73.       else if (i_ptr->todam < 0)
  74.         value = 0;
  75.       else if (i_ptr->toac < 0)
  76.         value = 0;
  77.       else
  78.         /* use 5, because missiles generally appear in groups of 20,
  79.            so 20 * 5 == 100, which is comparable to weapon bonus above */
  80.         value = i_ptr->cost+(i_ptr->tohit+i_ptr->todam+i_ptr->toac)*5;
  81.     }
  82.     }
  83.   else if ((i_ptr->tval == TV_SCROLL1) || (i_ptr->tval == TV_SCROLL2) ||
  84.        (i_ptr->tval == TV_POTION1) || (i_ptr->tval == TV_POTION2))
  85.     {    /* Potions, Scrolls, and Food    */
  86.       if (!known1_p(i_ptr))
  87.     value = 20;
  88.     }
  89.   else if (i_ptr->tval == TV_FOOD)
  90.     {
  91.       if ((i_ptr->subval < (ITEM_SINGLE_STACK_MIN + MAX_MUSH))
  92.       && !known1_p(i_ptr))
  93.     value = 1;
  94.     }
  95.   else if ((i_ptr->tval == TV_AMULET) || (i_ptr->tval == TV_RING))
  96.     {    /* Rings and amulets    */
  97.       if (!known1_p(i_ptr))
  98.     /* player does not know what type of ring/amulet this is */
  99.     value = 45;
  100.       else if (!known2_p(i_ptr))
  101.     /* player knows what type of ring, but does not know whether it is
  102.        cursed or not, if refuse to buy cursed objects here, then
  103.        player can use this to 'identify' cursed objects */
  104.     value = object_list[i_ptr->index].cost;
  105.     }
  106.   else if ((i_ptr->tval == TV_STAFF) || (i_ptr->tval == TV_WAND))
  107.     {    /* Wands and staffs*/
  108.       if (!known1_p(i_ptr))
  109.     {
  110.       if (i_ptr->tval == TV_WAND)
  111.         value = 50;
  112.       else
  113.         value = 70;
  114.     }
  115.       else if (known2_p(i_ptr))
  116.     value = i_ptr->cost + (i_ptr->cost / 20) * i_ptr->p1;
  117.     }
  118.   /* picks and shovels */
  119.   else if (i_ptr->tval == TV_DIGGING)
  120.     {
  121.       if (!known2_p(i_ptr))
  122.     value = object_list[i_ptr->index].cost;
  123.       else
  124.     {
  125.       if (i_ptr->p1 < 0)
  126.         value = 0;
  127.       else
  128.         {
  129.           /* some digging tools start with non-zero p1 values, so only
  130.          multiply the plusses by 100, make sure result is positive */
  131.           value = i_ptr->cost
  132.         + (i_ptr->p1 - object_list[i_ptr->index].p1) * 100;
  133.           if (value < 0)
  134.         value = 0;
  135.         }
  136.     }
  137.     }
  138.   /* multiply value by number of items if it is a group stack item */
  139.   if (i_ptr->subval > ITEM_GROUP_MIN) /* do not include torches here */
  140.     value = value * i_ptr->number;
  141.   return(value);
  142. }
  143.  
  144.  
  145. /* Asking price for an item                -RAK-    */
  146. int32 sell_price(snum, max_sell, min_sell, item)
  147. int snum;
  148. int32 *max_sell, *min_sell;
  149. inven_type *item;
  150. {
  151.   register int32 i;
  152.   register store_type *s_ptr;
  153.  
  154.   s_ptr = &store[snum];
  155.   i = item_value(item);
  156.   /* check item->cost in case it is cursed, check i in case it is damaged */
  157.   if ((item->cost > 0) && (i > 0))
  158.     {
  159.       i = i * rgold_adj[owners[s_ptr->owner].owner_race][py.misc.prace] / 100;
  160.       if (i < 1)  i = 1;
  161.       *max_sell = i * owners[s_ptr->owner].max_inflate / 100;
  162.       *min_sell = i * owners[s_ptr->owner].min_inflate / 100;
  163.       if (min_sell > max_sell)    min_sell = max_sell;
  164.       return(i);
  165.     }
  166.   else
  167.     /* don't let the item get into the store inventory */
  168.     return(0);
  169. }
  170.  
  171.  
  172. /* Check to see if he will be carrying too many objects    -RAK-    */
  173. int store_check_num(t_ptr, store_num)
  174. inven_type *t_ptr;
  175. int store_num;
  176. {
  177.   register int store_check, i;
  178.   register store_type *s_ptr;
  179.   register inven_type *i_ptr;
  180.  
  181.   store_check = FALSE;
  182.   s_ptr = &store[store_num];
  183.   if (s_ptr->store_ctr < STORE_INVEN_MAX)
  184.     store_check = TRUE;
  185.   else if (t_ptr->subval >= ITEM_SINGLE_STACK_MIN)
  186.     for (i = 0; i < s_ptr->store_ctr; i++)
  187.       {
  188.     i_ptr = &s_ptr->store_inven[i].sitem;
  189.     /* note: items with subval of gte ITEM_SINGLE_STACK_MAX only stack
  190.        if their subvals match */
  191.     if (i_ptr->tval == t_ptr->tval && i_ptr->subval == t_ptr->subval
  192.         && ((int)i_ptr->number + (int)t_ptr->number < 256)
  193.         && (t_ptr->subval < ITEM_GROUP_MIN
  194.         || (i_ptr->p1 == t_ptr->p1)))
  195.       store_check = TRUE;
  196.       }
  197.   return(store_check);
  198. }
  199.  
  200.  
  201. /* Insert INVEN_MAX at given location    */
  202. static void insert_store(store_num, pos, icost, i_ptr)
  203. register int pos;
  204. int store_num;
  205. int32 icost;
  206. inven_type *i_ptr;
  207. {
  208.   register int i;
  209.   register store_type *s_ptr;
  210.  
  211.   s_ptr = &store[store_num];
  212.   for (i = s_ptr->store_ctr-1; i >= pos; i--)
  213.     s_ptr->store_inven[i+1] = s_ptr->store_inven[i];
  214.   s_ptr->store_inven[pos].sitem = *i_ptr;
  215.   s_ptr->store_inven[pos].scost = -icost;
  216.   s_ptr->store_ctr++;
  217. }
  218.  
  219.  
  220. /* Add the item in INVEN_MAX to stores inventory.    -RAK-    */
  221. void store_carry(store_num, ipos, t_ptr)
  222. int store_num;
  223. int *ipos;
  224. inven_type *t_ptr;
  225. {
  226.   int item_num, item_val, flag;
  227.   register int typ, subt;
  228.   int32 icost, dummy;
  229.   register inven_type *i_ptr;
  230.   register store_type *s_ptr;
  231.  
  232.   *ipos = -1;
  233.   if (sell_price(store_num, &icost, &dummy, t_ptr) > 0)
  234.     {
  235.       s_ptr = &store[store_num];
  236.       item_val = 0;
  237.       item_num = t_ptr->number;
  238.       flag = FALSE;
  239.       typ  = t_ptr->tval;
  240.       subt = t_ptr->subval;
  241.       do
  242.     {
  243.       i_ptr = &s_ptr->store_inven[item_val].sitem;
  244.       if (typ == i_ptr->tval)
  245.         {
  246.           if (subt == i_ptr->subval && /* Adds to other item    */
  247.           subt >= ITEM_SINGLE_STACK_MIN
  248.           && (subt < ITEM_GROUP_MIN || i_ptr->p1 == t_ptr->p1))
  249.         {
  250.           *ipos = item_val;
  251.           i_ptr->number += item_num;
  252.           /* must set new scost for group items, do this only for items
  253.              strictly greater than group_min, not for torches, this
  254.              must be recalculated for entire group */
  255.           if (subt > ITEM_GROUP_MIN)
  256.             {
  257.               (void) sell_price (store_num, &icost, &dummy, i_ptr);
  258.               s_ptr->store_inven[item_val].scost = -icost;
  259.             }
  260.           /* must let group objects (except torches) stack over 24
  261.              since there may be more than 24 in the group */
  262.           else if (i_ptr->number > 24)
  263.             i_ptr->number = 24;
  264.           flag = TRUE;
  265.         }
  266.         }
  267.       else if (typ > i_ptr->tval)
  268.         {        /* Insert into list        */
  269.           insert_store(store_num, item_val, icost, t_ptr);
  270.           flag = TRUE;
  271.           *ipos = item_val;
  272.         }
  273.       item_val++;
  274.     }
  275.       while ((item_val < s_ptr->store_ctr) && (!flag));
  276.       if (!flag)    /* Becomes last item in list    */
  277.     {
  278.       insert_store(store_num, (int)s_ptr->store_ctr, icost, t_ptr);
  279.       *ipos = s_ptr->store_ctr - 1;
  280.     }
  281.     }
  282. }
  283.  
  284. /* Destroy an item in the stores inventory.  Note that if    */
  285. /* "one_of" is false, an entire slot is destroyed    -RAK-    */
  286. void store_destroy(store_num, item_val, one_of)
  287. int store_num, item_val;
  288. int one_of;
  289. {
  290.   register int j, number;
  291.   register store_type *s_ptr;
  292.   register inven_type *i_ptr;
  293.  
  294.   s_ptr = &store[store_num];
  295.   i_ptr = &s_ptr->store_inven[item_val].sitem;
  296.  
  297.   /* for single stackable objects, only destroy one half on average,
  298.      this will help ensure that general store and alchemist have
  299.      reasonable selection of objects */
  300.   if ((i_ptr->subval >= ITEM_SINGLE_STACK_MIN) &&
  301.       (i_ptr->subval <= ITEM_SINGLE_STACK_MAX))
  302.     {
  303.       if (one_of)
  304.     number = 1;
  305.       else
  306.     number = randint((int)i_ptr->number);
  307.     }
  308.   else
  309.     number = i_ptr->number;
  310.  
  311.   if (number != i_ptr->number)
  312.     i_ptr->number -= number;
  313.   else
  314.     {
  315.       for (j = item_val; j < s_ptr->store_ctr-1; j++)
  316.     s_ptr->store_inven[j] = s_ptr->store_inven[j+1];
  317.       invcopy(&s_ptr->store_inven[s_ptr->store_ctr-1].sitem, OBJ_NOTHING);
  318.       s_ptr->store_inven[s_ptr->store_ctr-1].scost = 0;
  319.       s_ptr->store_ctr--;
  320.     }
  321. }
  322.  
  323.  
  324. /* Initializes the stores with owners            -RAK-    */
  325. void store_init()
  326. {
  327.   register int i, j, k;
  328.   register store_type *s_ptr;
  329.  
  330.   i = MAX_OWNERS / MAX_STORES;
  331.   for (j = 0; j < MAX_STORES; j++)
  332.     {
  333.       s_ptr = &store[j];
  334.       s_ptr->owner = MAX_STORES*(randint(i)-1) + j;
  335.       s_ptr->insult_cur = 0;
  336.       s_ptr->store_open = 0;
  337.       s_ptr->store_ctr    = 0;
  338.       s_ptr->good_buy = 0;
  339.       s_ptr->bad_buy = 0;
  340.       for (k = 0; k < STORE_INVEN_MAX; k++)
  341.     {
  342.       invcopy(&s_ptr->store_inven[k].sitem, OBJ_NOTHING);
  343.       s_ptr->store_inven[k].scost = 0;
  344.     }
  345.     }
  346. }
  347.  
  348.  
  349. /* Creates an item and inserts it into store's inven    -RAK-    */
  350. static void store_create(store_num)
  351. int store_num;
  352. {
  353.   register int i, tries;
  354.   int cur_pos, dummy;
  355.   register store_type *s_ptr;
  356.   register inven_type *t_ptr;
  357.  
  358.   tries = 0;
  359.   cur_pos = popt();
  360.   s_ptr = &store[store_num];
  361.   do
  362.     {
  363.       i = store_choice[store_num][randint(STORE_CHOICES)-1];
  364.       invcopy(&t_list[cur_pos], i);
  365.       magic_treasure(cur_pos, OBJ_TOWN_LEVEL);
  366.       t_ptr = &t_list[cur_pos];
  367.       if (store_check_num(t_ptr, store_num))
  368.     {
  369.       if ((t_ptr->cost > 0) &&    /* Item must be good    */
  370.           (t_ptr->cost < owners[s_ptr->owner].max_cost))
  371.         {
  372.           /* equivalent to calling ident_spell(), except will not
  373.          change the object_ident array */
  374.           store_bought(t_ptr);
  375.           store_carry(store_num, &dummy, t_ptr);
  376.           tries = 10;
  377.         }
  378.     }
  379.       tries++;
  380.     }
  381.   while (tries <= 3);
  382.   pusht((int8u)cur_pos);
  383. }
  384.  
  385.  
  386. /* Initialize and up-keep the store's inventory.        -RAK-    */
  387. void store_maint()
  388. {
  389.   register int i, j;
  390.   register store_type *s_ptr;
  391.  
  392.   for (i = 0; i < MAX_STORES; i++)
  393.     {
  394.       s_ptr = &store[i];
  395.       s_ptr->insult_cur = 0;
  396.       if (s_ptr->store_ctr >= STORE_MIN_INVEN)
  397.     {
  398.       j = randint(STORE_TURN_AROUND);
  399.       if (s_ptr->store_ctr >= STORE_MAX_INVEN)
  400.         j += 1 + s_ptr->store_ctr - STORE_MAX_INVEN;
  401.       while (--j >= 0)
  402.         store_destroy(i, randint((int)s_ptr->store_ctr)-1, FALSE);
  403.     }
  404.  
  405.       if (s_ptr->store_ctr <= STORE_MAX_INVEN)
  406.     {
  407.       j = randint(STORE_TURN_AROUND);
  408.       if (s_ptr->store_ctr < STORE_MIN_INVEN)
  409.         j += STORE_MIN_INVEN - s_ptr->store_ctr;
  410.       while (--j >= 0)
  411.         store_create(i);
  412.     }
  413.     }
  414. }
  415.  
  416. /* eliminate need to bargain if player has haggled well in the past   -DJB- */
  417. int noneedtobargain(store_num, minprice)
  418. int store_num;
  419. int32 minprice;
  420. {
  421.   register int flagnoneed;
  422.   register store_type *s_ptr;
  423.  
  424.   s_ptr = &store[store_num];
  425.   flagnoneed = ((s_ptr->good_buy == MAX_SHORT)
  426.         || (s_ptr->good_buy > 3 * s_ptr->bad_buy + 5 + minprice/50));
  427.   return (flagnoneed);
  428. }
  429.  
  430.  
  431. /* update the bargin info                    -DJB- */
  432. void updatebargain(store_num, price, minprice)
  433. int store_num;
  434. int32 price, minprice;
  435. {
  436.   register store_type *s_ptr;
  437.  
  438.   s_ptr = &store[store_num];
  439.   if (minprice > 9)
  440.     if (price == minprice)
  441.       {
  442.     if (s_ptr->good_buy < MAX_SHORT)
  443.       s_ptr->good_buy++;
  444.       }
  445.     else
  446.       {
  447.     if (s_ptr->bad_buy < MAX_SHORT)
  448.       s_ptr->bad_buy++;
  449.       }
  450. }
  451.